﻿using System;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web;
using Moq;

namespace MVCHelperExtensions.Test
{
  public static class TestHelpers
  {
    #region Blatantly pilfered test code from the ASP.NET MVC source

    public static HtmlHelper GetHtmlHelperWithDefaultHttpContext()
    {
      HttpContextBase httpcontext = GetHttpContext("/app/", null, null);
      RouteCollection rt = new RouteCollection();
      rt.Add(new Route("{controller}/{action}/{id}", null) { Defaults = new RouteValueDictionary(new { id = "defaultid" }) });
      rt.Add("namedroute", new Route("named/{controller}/{action}/{id}", null) { Defaults = new RouteValueDictionary(new { id = "defaultid" }) });
      RouteData rd = new RouteData();
      rd.Values.Add("controller", "home");
      rd.Values.Add("action", "oldaction");

      ViewDataDictionary vdd = new ViewDataDictionary();

      Mock<ViewContext> mockViewContext = new Mock<ViewContext>();
      mockViewContext.Expect(c => c.HttpContext).Returns(httpcontext);
      mockViewContext.Expect(c => c.RouteData).Returns(rd);
      mockViewContext.Expect(c => c.ViewData).Returns(vdd);
      Mock<IViewDataContainer> mockVdc = new Mock<IViewDataContainer>();
      mockVdc.Expect(vdc => vdc.ViewData).Returns(vdd);

      HtmlHelper htmlHelper = new HtmlHelper(mockViewContext.Object, mockVdc.Object, rt);
      return htmlHelper;
    }

    public const string AppPathModifier = "/TEST_APP_MODIFIER";

    public static HttpContextBase GetHttpContext(string appPath, string requestPath, string httpMethod)
    {
      return GetHttpContext(appPath, requestPath, httpMethod, Uri.UriSchemeHttp.ToString(), -1);
    }

    public static HttpContextBase GetHttpContext(string appPath, string requestPath, string httpMethod, string protocol, int port)
    {
      Mock<HttpContextBase> mockHttpContext = new Mock<HttpContextBase>();

      if (!String.IsNullOrEmpty(appPath))
      {
        mockHttpContext.Expect(o => o.Request.ApplicationPath).Returns(appPath);
      }
      if (!String.IsNullOrEmpty(requestPath))
      {
        mockHttpContext.Expect(o => o.Request.AppRelativeCurrentExecutionFilePath).Returns(requestPath);
      }

      Uri uri;

      if (port >= 0)
      {
        uri = new Uri(protocol + "://localhost" + ":" + Convert.ToString(port));
      }
      else
      {
        uri = new Uri(protocol + "://localhost");
      }
      mockHttpContext.Expect(o => o.Request.Url).Returns(uri);

      mockHttpContext.Expect(o => o.Request.PathInfo).Returns(String.Empty);
      if (!String.IsNullOrEmpty(httpMethod))
      {
        mockHttpContext.Expect(o => o.Request.HttpMethod).Returns(httpMethod);
      }

      mockHttpContext.Expect(o => o.Session).Returns((HttpSessionStateBase)null);
      mockHttpContext.Expect(o => o.Response.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(r => AppPathModifier + r);
      return mockHttpContext.Object;
    }

    public static UrlHelper GetUrlHelperWithDefaultHttpContext()
    {
      HttpContextBase httpcontext = GetHttpContext("/app/", null, null);
      RouteCollection rt = new RouteCollection();
      rt.Add(new Route("{controller}/{action}/{id}", null) { Defaults = new RouteValueDictionary(new { id = "defaultid" }) });
      rt.Add("namedroute", new Route("named/{controller}/{action}/{id}", null) { Defaults = new RouteValueDictionary(new { id = "defaultid" }) });
      RouteData rd = new RouteData();
      rd.Values.Add("controller", "home");
      rd.Values.Add("action", "oldaction");

      UrlHelper urlHelper = new UrlHelper(new RequestContext(httpcontext, rd), rt);
      return urlHelper;
    }
    #endregion
  }

  #region Test data types
  #region Types with default ID's
  class TestModel
  {
    public int ID { get; set; }
  }

  class TestModelWithId
  {
    public int Id { get; set; }
  }

  class TestModelWithid
  {
    public int id { get; set; }
  }

  class TestModelWith_ID
  {
    public int _ID { get; set; }
  }

  class TestModelWith_Id
  {
    public int _Id { get; set; }
  }

  class TestModelWith_id
  {
    public int _id { get; set; }
  }

  class TestModelWithoutID
  {
  }

  class TestModelWithInvalidID
  {
    public string ID { get; set; }
  }
  #endregion

  class TestModelWithAlternateID
  {
    [MVCHelperIdentifier]
    public int AlternateID { get; set; }
  }

  [MVCHelperControllerName("OtherController")]
  class TestModelWithControllerName_OtherController
  {
    public int ID { get; set; }
  }

  [MVCHelperIndexMethodName("OtherIndex")]
  class TestModelWithIndexMethodName_OtherIndex
  {
    public int ID { get; set; }
  }

  [MVCHelperDetailsMethodName("OtherDetails")]
  class TestModelWithDetailsMethodName_OtherDetails
  {
    public int ID { get; set; }
  }

  [MVCHelperEditMethodName("OtherEdit")]
  class TestModelWithEditMethodName_OtherEdit
  {
    public int ID { get; set; }
  }

  [MVCHelperNewMethodName("OtherNew")]
  class TestModelWithNewMethodName_OtherNew
  {
    public int ID { get; set; }
  }
  #endregion
}
